package cn.tedu.csmall.passport.service.impl;

import cn.tedu.csmall.passport.ex.ServiceException;
import cn.tedu.csmall.passport.mappers.AdminMapper;
import cn.tedu.csmall.passport.mappers.AdminRoleMapper;
import cn.tedu.csmall.passport.pojo.dto.AdminAddNewDTO;
import cn.tedu.csmall.passport.pojo.dto.AdminLoginDTO;
import cn.tedu.csmall.passport.pojo.entity.Admin;
import cn.tedu.csmall.passport.pojo.entity.AdminRole;
import cn.tedu.csmall.passport.pojo.vo.AdminListItemVO;
import cn.tedu.csmall.passport.pojo.vo.AdminStandardVO;
import cn.tedu.csmall.passport.security.AdminDetails;
import cn.tedu.csmall.passport.service.IAdminService;
import cn.tedu.csmall.passport.web.ServiceCode;
import com.alibaba.fastjson.JSON;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;

@Slf4j
@Service
public class AdminServiceImpl implements IAdminService {
    @Value("${csmall.jwt.secret-key}")
    private String secretKey;
    @Value("${csmall.jwt.duration-in-minute}")
    private long durationInMinute;

    @Autowired
    AdminMapper adminMapper;
    @Autowired
    AdminRoleMapper adminRoleMapper;
    @Autowired
    AuthenticationManager authenticationManager;

    @Override
    public String login(AdminLoginDTO adminLoginDTO) {
        log.debug("开始处理【管理员登录】的业务，参数：{}", adminLoginDTO);
        Authentication authentication
                = new UsernamePasswordAuthenticationToken(
                adminLoginDTO.getUsername(), adminLoginDTO.getPassword());
        Authentication authenticateResult = authenticationManager.authenticate(authentication);//认证管理器
        SecurityContextHolder.getContext().setAuthentication(authenticateResult);

        Object principal = authenticateResult.getPrincipal();
        AdminDetails adminDetails = (AdminDetails) principal;

        String username = adminDetails.getUsername();
        Long id = adminDetails.getId();
        Collection<GrantedAuthority> authorities = adminDetails.getAuthorities();
        String authoritiesJsonString = JSON.toJSONString(authorities);

        Date date = new Date(System.currentTimeMillis() + durationInMinute * 60 * 1000);
        HashMap<String, Object> claims = new HashMap<>();
        //claims.put("id", 9527l);
        claims.put("id",id);
        claims.put("username", username);
        claims.put("authoritiesJsonString", authoritiesJsonString);
        String jwt = Jwts
                .builder()
                .setHeaderParam("alg", "HS256")
                .setHeaderParam("typ", "JWT")
                .setClaims(claims)
                .setExpiration(date)
                .signWith(SignatureAlgorithm.HS256, secretKey)
                .compact();
        log.debug("{}",jwt);
        return jwt;

    }
    public void addNew(AdminAddNewDTO adminAddNewDTO) {
        log.debug("{}", adminAddNewDTO);
        int count = adminMapper.countByusername(adminAddNewDTO.getUsername());
        if (count > 0) {
            String message = "用户名被占用";
            throw new ServiceException(ServiceCode.ERR_CONFLICT, message);
        }
        count = adminMapper.countByPhone(adminAddNewDTO.getPhone());
        if (count > 0) {
            String message = "手机号码被占用";
            throw new ServiceException(ServiceCode.ERR_CONFLICT, message);
        }
        count = adminMapper.countByEmail(adminAddNewDTO.getEmail());
        if (count > 0) {
            String message = "邮箱被占用";
            throw new ServiceException(ServiceCode.ERR_CONFLICT, message);
        }

        Admin admin = new Admin();
        BeanUtils.copyProperties(adminAddNewDTO, admin);
        admin.setLoginCount(0);
        //TODO 从参数对象中取出密码，进行加密，再存入到Admin对象中
        count = adminMapper.insert(admin);
        if (count != 1) {
            String message = "服务器忙";
            throw new ServiceException(ServiceCode.ERR_INSERT, message);
        }
        // 插入管理员与角色关联的数据
        Long[] roleIds = adminAddNewDTO.getRoleIds();
        AdminRole[] adminRoles = new AdminRole[roleIds.length];
        LocalDateTime now = LocalDateTime.now();
        for (int i = 0; i < roleIds.length;i++){
            AdminRole adminRole = new AdminRole();
            adminRole.setAdminId(admin.getId());
            adminRole.setRoleId(roleIds[i]);
            adminRole.setGmtCreate(now);
            adminRole.setGmtModified(now);
            adminRoles[i] = adminRole;
        }
        count = adminRoleMapper.insertBatch(adminRoles);
        if(count != roleIds.length){
            throw new ServiceException(ServiceCode.ERR_INSERT,"服务器忙 稍后重试");
        }
    }

    public void delete(Long id) {
        if (id == 1) {
            // 是：抛出异常（ERR_NOT_FOUND）
            String message = "删除管理员失败，尝试删除的管理员数据不存在！";
            log.debug(message);
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
        }
        AdminStandardVO queryResult = adminMapper.getStandardById(id);
        if (queryResult == null) {
            String message = "删除管理员失败 尝试删除的管理员不存在";
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, message);
        }
        int count = adminMapper.deleteById(id);
        if (count != 1) {
            String message = "删除失败 服务器忙";
            throw new ServiceException(ServiceCode.ERR_DELETE, message);
        }

        // 删除管理员与角色的关联数据
        int rows = adminRoleMapper.deleteByAdminId(id);
        if (rows < 1) {
            String message = "删除管理员失败 服务器忙";
            throw new ServiceException(ServiceCode.ERR_DELETE, message);
        }

    }

    public List<AdminListItemVO> list() {
        List<AdminListItemVO> list = adminMapper.list();
        Iterator<AdminListItemVO> iterator = list.iterator();
        while (iterator.hasNext()) {
            AdminListItemVO item = iterator.next();
            if (item.getId() == 1) {
                iterator.remove();
                break;
            }
        }
        return list;
    }

    public void setEnable(Long id) {
        updateEnableById(id, 1);
    }

    public void setDisable(Long id) {
        updateEnableById(id, 0);
    }



    private void updateEnableById(Long id, Integer enable) {
        String[] s = {"禁用", "启用"};
        if (id == 1) {
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, s[enable] + "管理员失败");
        }
        AdminStandardVO queryResult = adminMapper.getStandardById(id);
        if (queryResult == null) {
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND, "根据id查询管理员不存在");
        }
        if (queryResult.getEnable().equals(enable)) {
            throw new ServiceException(ServiceCode.ERR_CONFLICT, s[enable] + "管理员失败");
        }
        Admin admin = new Admin();
        admin.setId(id);
        admin.setEnable(enable);
        int count = adminMapper.update(admin);
        if (count != 1) {
            throw new ServiceException(ServiceCode.ERR_UPDATE, "服务器忙");
        }

    }
}
